package com.example.netty.client.udp;

import com.example.netty.service.NettyClient;
import com.example.netty.model.CallBack;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.AttributeKey;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

public class UdpClient implements NettyClient {


    private final static Logger logger = LoggerFactory.getLogger(UdpClient.class);

    /**
     * 设置通用key
     */
    public static final AttributeKey<CallBack> callBackAttributeKey = AttributeKey.valueOf("callBackAttributeKey");

    private Channel clientChannel;

    private final InetSocketAddress socketAddress;

    public UdpClient(String ip, int port, int bindPort) throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup();
        UdpClientHandler udpClientHandler = new UdpClientHandler();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioDatagramChannel.class)
                .option(ChannelOption.SO_BROADCAST, true)
                .handler(udpClientHandler);

        this.clientChannel = bootstrap.bind(bindPort).sync().channel();
        this.socketAddress = new InetSocketAddress(ip, port);
    }


    /**
     * 发送消息并同步等待数据返回
     *
     * @param msg
     * @param timeOutMilliseconds
     * @return
     */
    public synchronized String send(String msg, long timeOutMilliseconds) throws Exception {
        CallBack callBack = new CallBack(1);
        clientChannel.attr(callBackAttributeKey).set(callBack);
        clientChannel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(msg, CharsetUtil.US_ASCII), socketAddress)).sync();
        callBack.await(timeOutMilliseconds, TimeUnit.MILLISECONDS);
        return callBack.getResponse();
    }
}
